---
title: Declarative Builder
---

import { TabItem, Tabs } from '@astrojs/starlight/components'

Daytona's declarative builder provides a powerful, code-first approach to defining dependencies for Sandboxes. Instead of importing images from a container registry, you can programmatically define them using the SDK.

## Overview

The declarative builder system supports two primary workflows:

1. [**Declarative Images**](#declarative-image-building): Build images with varying dependencies _on demand_ when creating Sandboxes
2. [**Pre-built Snapshots**](#creating-pre-built-snapshots): Create and register _ready-to-use_ [Snapshots](/docs/snapshots) that can be shared across multiple Sandboxes

### Declarative Image Building

You can create declarative images on-the-fly when creating Sandboxes. This is ideal for iterating quickly without creating separate Snapshots.

Declarative images are cached for 24 hours, and will be automatically reused when running the same script. Thus, subsequent runs on the same Runner will be almost instantaneous.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">
```python
# Define a simple declarative image with Python packages
declarative_image = (
    Image.debian_slim("3.12")
    .pip_install(["requests", "pytest"])
    .workdir("/home/daytona")
)

# Create a new Sandbox with the declarative image and stream the build logs
sandbox = daytona.create(
    CreateSandboxFromImageParams(image=declarative_image),
    timeout=0,
    on_snapshot_create_logs=print,
)
```
</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// Define a simple declarative image with Python packages
const declarativeImage = Image.debianSlim('3.12')
  .pipInstall(['requests', 'pytest'])
  .workdir('/home/daytona')

// Create a new Sandbox with the declarative image and stream the build logs
const sandbox = await daytona.create(
  {
    image: declarativeImage,
  },
  {
    timeout: 0,
    onSnapshotCreateLogs: console.log,
  }
)
```
</TabItem>
</Tabs>

See: [CreateSandboxFromImageParams (Python SDK)](/docs/python-sdk/sync/daytona#createsandboxfromimageparams), [CreateSandboxFromImageParams (TypeScript SDK)](/docs/typescript-sdk/daytona#createsandboxfromimageparams)

### Creating Pre-built Snapshots

For images that will be reused across multiple Sandboxes, create a pre-built Snapshot. This Snapshot will remain visible in the Daytona dashboard and be permanently cached, ensuring instant availability without rebuilding.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">
```python
# Create a simple Python data science image
snapshot_name = "data-science-snapshot"

image = (
    Image.debian_slim("3.12")
    .pip_install(["pandas", "numpy"])
    .workdir("/home/daytona")
)

# Create the Snapshot and stream the build logs
daytona.snapshot.create(
    CreateSnapshotParams(
        name=snapshot_name,
        image=image,
    ),
    on_logs=print,
)

# Create a new Sandbox using the pre-built Snapshot
sandbox = daytona.create(
  CreateSandboxFromSnapshotParams(snapshot=snapshot_name)
)
```
</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// Create a simple Python data science image
const snapshotName = 'data-science-snapshot'

const image = Image.debianSlim('3.12')
  .pipInstall(['pandas', 'numpy'])
  .workdir('/home/daytona')

// Create the Snapshot and stream the build logs
await daytona.snapshot.create(
  {
      name: snapshotName,
      image,
  },
  {
      onLogs: console.log,
  }
)

// Create a new Sandbox using the pre-built Snapshot
const sandbox = await daytona.create({
  snapshot: snapshotName,
})
```
</TabItem>
</Tabs>

See: [CreateSnapshotParams (Python SDK)](/docs/python-sdk/sync/snapshot#createsnapshotparams), [CreateSnapshotParams (TypeScript SDK)](/docs/typescript-sdk/snapshot#createsnapshotparams)

## Image Configuration

The Daytona SDK provides methods to define images programmatically using the Daytona SDK. You can specify base images, install packages, add files, set environment variables, and more.

For a complete API reference and method signatures, check the [Python](/docs/python-sdk/common/image) and [TypeScript](/docs/typescript-sdk/image) SDK references.

### Base Image Selection

These examples demonstrate how to select and configure base images:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">
```python
# Create an image from a base
image = Image.base("python:3.12-slim-bookworm")

# Use a Debian slim image with Python 3.12
image = Image.debian_slim("3.12")
```
</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// Create an image from a base
const image = Image.base('python:3.12-slim-bookworm')

// Use a Debian slim image with Python 3.12
const image = Image.debianSlim('3.12')
```
</TabItem>
</Tabs>

See: [base (Python SDK)](/docs/python-sdk/common/image#imagebase), [debian_slim (Python SDK)](/docs/python-sdk/common/image#imagedebian_slim), [base (TypeScript SDK)](/docs/typescript-sdk/image#base), [debianSlim (TypeScript SDK)](/docs/typescript-sdk/image#debianslim)

### Package Management

Use these methods to install Python packages and dependencies:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">
```python
# Add pip packages
image = Image.debian_slim("3.12").pip_install("requests", "pandas")

# Install from requirements.txt
image = Image.debian_slim("3.12").pip_install_from_requirements("requirements.txt")

# Install from pyproject.toml (with optional dependencies)
image = Image.debian_slim("3.12").pip_install_from_pyproject("pyproject.toml", optional_dependencies=["dev"])
```
</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// Add pip packages
const image = Image.debianSlim('3.12').pipInstall(['requests', 'pandas'])

// Install from requirements.txt
const image = Image.debianSlim('3.12').pipInstallFromRequirements('requirements.txt')

// Install from pyproject.toml (with optional dependencies)
const image = Image.debianSlim('3.12').pipInstallFromPyproject('pyproject.toml', { 
  optionalDependencies: ['dev'] 
})
```
</TabItem>
</Tabs>

See: [pip_install (Python SDK)](/docs/python-sdk/common/image#imagepip_install), [pip_install_from_requirements (Python SDK)](/docs/python-sdk/common/image#imagepip_install_from_requirements), [pip_install_from_pyproject (Python SDK)](/docs/python-sdk/common/image#imagepip_install_from_pyproject), [pipInstall (TypeScript SDK)](/docs/typescript-sdk/image#pipinstall), [pipInstallFromRequirements (TypeScript SDK)](/docs/typescript-sdk/image#pipinstallfromrequirements), [pipInstallFromPyproject (TypeScript SDK)](/docs/typescript-sdk/image#pipinstallfrompyproject)

### File System Operations

These examples show how to add files and directories to your image:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">
```python
# Add a local file
image = Image.debian_slim("3.12").add_local_file("package.json", "/home/daytona/package.json")

# Add a local directory
image = Image.debian_slim("3.12").add_local_dir("src", "/home/daytona/src")
```
</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// Add a local file
const image = Image.debianSlim('3.12').addLocalFile('package.json', '/home/daytona/package.json')

// Add a local directory
const image = Image.debianSlim('3.12').addLocalDir('src', '/home/daytona/src')
```
</TabItem>
</Tabs>

See: [add_local_file (Python SDK)](/docs/python-sdk/common/image#imageadd_local_file), [add_local_dir (Python SDK)](/docs/python-sdk/common/image#imageadd_local_dir), [addLocalFile (TypeScript SDK)](/docs/typescript-sdk/image#addlocalfile), [addLocalDir (TypeScript SDK)](/docs/typescript-sdk/image#addlocaldir)

### Environment Configuration

Configure environment variables and working directories with these methods:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">
```python
# Set environment variables
image = Image.debian_slim("3.12").env({"PROJECT_ROOT": "/home/daytona"})

# Set working directory
image = Image.debian_slim("3.12").workdir("/home/daytona")
```
</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// Set environment variables
const image = Image.debianSlim('3.12').env({ PROJECT_ROOT: '/home/daytona' })

// Set working directory
const image = Image.debianSlim('3.12').workdir('/home/daytona')
```
</TabItem>
</Tabs>

See: [env (Python SDK)](/docs/python-sdk/common/image#imageenv), [workdir (Python SDK)](/docs/python-sdk/common/image#imageworkdir), [env (TypeScript SDK)](/docs/typescript-sdk/image#env), [workdir (TypeScript SDK)](/docs/typescript-sdk/image#workdir)

### Commands and Entrypoints

Execute commands during build and configure container startup behavior:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">
```python
# Run shell commands during build
image = Image.debian_slim("3.12").run_commands(
    'apt-get update && apt-get install -y git',
    'groupadd -r daytona && useradd -r -g daytona -m daytona',
    'mkdir -p /home/daytona/workspace'
)

# Set entrypoint
image = Image.debian_slim("3.12").entrypoint(["/bin/bash"])

# Set default command
image = Image.debian_slim("3.12").cmd(["/bin/bash"])
```
</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// Run shell commands during build
const image = Image.debianSlim('3.12').runCommands(
    'apt-get update && apt-get install -y git',
    'groupadd -r daytona && useradd -r -g daytona -m daytona',
    'mkdir -p /home/daytona/workspace'
)

// Set entrypoint
const image = Image.debianSlim('3.12').entrypoint(['/bin/bash'])

// Set default command
const image = Image.debianSlim('3.12').cmd(['/bin/bash'])
```
</TabItem>
</Tabs>

See: [run_commands (Python SDK)](/docs/python-sdk/common/image#imagerun_commands), [entrypoint (Python SDK)](/docs/python-sdk/common/image#imageentrypoint), [cmd (Python SDK)](/docs/python-sdk/common/image#imagecmd), [runCommands (TypeScript SDK)](/docs/typescript-sdk/image#runcommands), [entrypoint (TypeScript SDK)](/docs/typescript-sdk/image#entrypoint), [cmd (TypeScript SDK)](/docs/typescript-sdk/image#cmd)

### Dockerfile Integration

Integrate existing Dockerfiles or add custom Dockerfile commands:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">
```python
# Add custom Dockerfile commands
image = Image.debian_slim("3.12").dockerfile_commands(["RUN echo 'Hello, world!'"])

# Use an existing Dockerfile
image = Image.from_dockerfile("Dockerfile")

# Extend an existing Dockerfile
image = Image.from_dockerfile("app/Dockerfile").pip_install(["numpy"])
```
</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// Add custom Dockerfile commands
const image = Image.debianSlim('3.12').dockerfileCommands(['RUN echo "Hello, world!"'])

// Use an existing Dockerfile
const image = Image.fromDockerfile('Dockerfile')

// Extend an existing Dockerfile
const image = Image.fromDockerfile("app/Dockerfile").pipInstall(['numpy'])
```
</TabItem>
</Tabs>

See: [dockerfile_commands (Python SDK)](/docs/python-sdk/common/image#imagedockerfile_commands), [from_dockerfile (Python SDK)](/docs/python-sdk/common/image#imagefrom_dockerfile), [dockerfileCommands (TypeScript SDK)](/docs/typescript-sdk/image#dockerfilecommands), [fromDockerfile (TypeScript SDK)](/docs/typescript-sdk/image#fromdockerfile)

## Best Practices

Use the following best practices when working with the declarative builder:

1. **Layer Optimization**: Group related operations to minimize Docker layers
2. **Cache Utilization**: Identical build commands and context will be cached and subsequent builds will be almost instant
3. **Security**: Create non-root users for application workloads
4. **Resource Efficiency**: Use slim base images when appropriate
5. **Context Minimization**: Only include necessary files in the build context
